﻿using Common;
using System.Collections.Concurrent;
using System.Net.Sockets;

namespace NewDevice.TCPIP
{
    /// <summary>
    /// 12路直流电压采集模块控制类 提供基于TCP/IP协议的12路直流电压采集功能
    /// </summary>
    [Obsolete("请使用Zh3412134M2_V2")]
    public class Zh3412134M2
    {
        #region 初始化设置指令

        //01 06 00 EF 00 09 //采样率设置为500Hz
        //01 06 00 E6 00 00 //关闭can自动上传
        //01 06 00 E4 00 01 //启用网口自动上传

        #endregion 初始化设置指令

        /// <summary>
        /// 服务器IP地址
        /// </summary>
        private string _serverIp;

        /// <summary>
        /// 服务器端口号
        /// </summary>
        private int _serverPort;

        /// <summary>
        /// TCP客户端对象
        /// </summary>
        private TcpClient _client = null!;

        /// <summary>
        /// 网络数据流
        /// </summary>
        private NetworkStream _stream = null!;

        /// <summary>
        /// 接收数据队列（线程安全）
        /// </summary>
        private readonly ConcurrentQueue<byte[]> _dataQueue = new ConcurrentQueue<byte[]>();

        /// <summary>
        /// 寄存器历史值缓存（通道号 -&gt; 历史值列表）
        /// </summary>
        private readonly Dictionary<int, List<short>?> _registerValues = new Dictionary<int, List<short>?>();

        /// <summary>
        /// 上次接收到数据的时间
        /// </summary>
        private DateTime _lastDataReceivedTime = DateTime.MinValue;

        /// <summary>
        /// 通信超时时间（秒）
        /// </summary>
        private const int TimeoutSeconds = 5;

        /// <summary>
        /// 任务取消令牌源
        /// </summary>
        private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();

        /// <summary>
        /// 线程同步锁对象
        /// </summary>
        private readonly Lock _lock = new Lock();

        /// <summary>
        /// 通信异常事件
        /// </summary>
        public event Action<string> OnCommunicationError = null!;

        /// <summary>
        /// 获取或设置每个寄存器的历史值列表的最大长度
        /// </summary>
        public int MaxHistorySize { get; set; } = 5000;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="serverIp">服务器IP地址，默认为127.0.0.1</param>
        /// <param name="serverPort">服务器端口号，默认为5000</param>
        public Zh3412134M2(string serverIp = "127.0.0.1", int serverPort = 5000)
        {
            _serverIp = serverIp;
            _serverPort = serverPort;
        }

        /// <summary>
        /// 获取或设置服务器IP地址
        /// </summary>
        public string ServerIp
        {
            get => _serverIp;
            set => _serverIp = value;
        }

        /// <summary>
        /// 获取或设置服务器端口号
        /// </summary>
        public int ServerPort
        {
            get => _serverPort;
            set => _serverPort = value;
        }

        public int MeasureRange { get; set; } = 30;

        /// <summary>
        /// 获取所有通道的电压历史值（已转换为实际电压值）
        /// </summary>
        /// <remarks>电压值计算公式：读值*30(量程)/10000，并保留3位小数</remarks>
        public Dictionary<int, List<double>> RegisterValues
        {
            get
            {
                lock (_lock)
                {
                    return _registerValues.ToDictionary(
                        kvp => kvp.Key,
                        kvp => kvp!.Value!.Select(v => Math.Round(v * MeasureRange / 10000.0, 3)).ToList()
                    );
                }
            }
        }

        /// <summary>
        /// 启动TCP客户端连接
        /// </summary>
        /// <returns>异步任务</returns>
        /// <exception cref="System.Net.Sockets.SocketException">网络连接失败时抛出</exception>
        public void Open()
        {
            _client = new TcpClient();
            MyLog.Debug($"Connecting to server at {_serverIp}:{_serverPort}...");
            _client.Connect(_serverIp, _serverPort);
            MyLog.Debug("Connected to server.");

            _stream = _client.GetStream();

            var receiveTask = Task.Run(() => ReceiveDataAsync(_cancellationTokenSource.Token));
            var processTask = Task.Run(() => ProcessDataAsync(_cancellationTokenSource.Token));
            var timeoutTask = Task.Run(() => CheckForTimeoutAsync(_cancellationTokenSource.Token));
        }

        /// <summary>
        /// 用于缓存不完整的数据包
        /// </summary>
        private byte[] _remainingData = [];

        /// <summary>
        /// 接收数据任务
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>异步任务</returns>
        private async Task ReceiveDataAsync(CancellationToken cancellationToken)
        {
            byte[] buffer = new byte[4096];

            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    int bytesRead = await _stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken);
                    if (bytesRead == 0)
                    {
                        MyLog.Debug("Server disconnected.");
                        break;
                    }

                    byte[] combinedData = new byte[_remainingData.Length + bytesRead];
                    Buffer.BlockCopy(_remainingData, 0, combinedData, 0, _remainingData.Length);
                    Buffer.BlockCopy(buffer, 0, combinedData, _remainingData.Length, bytesRead);

                    int offset = 0;
                    while (offset + 29 <= combinedData.Length)
                    {
                        if (combinedData[offset] == 0x01 && combinedData[offset + 1] == 0x03 && combinedData[offset + 2] == 0x18)
                        {
                            byte[] dataPacket = new byte[29];
                            Buffer.BlockCopy(combinedData, offset, dataPacket, 0, 29);
                            _dataQueue.Enqueue(dataPacket);
                            offset += 29;
                        }
                        else
                        {
                            offset++;
                        }
                    }

                    _remainingData = new byte[combinedData.Length - offset];
                    Buffer.BlockCopy(combinedData, offset, _remainingData, 0, _remainingData.Length);

                    _lastDataReceivedTime = DateTime.Now;
                }
                catch (Exception ex)
                {
                    MyLog.Debug($"Error receiving data: {ex.Message}");
                    OnCommunicationError?.Invoke($"Error receiving data: {ex.Message}");
                    break;
                }
            }
        }

        /// <summary>
        /// 数据处理任务
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>异步任务</returns>
        private async Task ProcessDataAsync(CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    if (_dataQueue.TryDequeue(out var data))
                    {
                        ParseReceivedData(data);
                    }
                    else
                    {
                        await Task.Delay(10, cancellationToken);
                    }
                }
                catch (Exception ex)
                {
                    MyLog.Debug($"Error processing data: {ex.Message}");
                    OnCommunicationError?.Invoke($"Error processing data: {ex.Message}");
                }
            }
        }

        /// <summary>
        /// 超时检测任务
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>异步任务</returns>
        private async Task CheckForTimeoutAsync(CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                await Task.Delay(1000, cancellationToken);

                if ((DateTime.Now - _lastDataReceivedTime).TotalSeconds > TimeoutSeconds)
                {
                    OnCommunicationError?.Invoke("No data received for a long time. Communication may be interrupted.");
                    _lastDataReceivedTime = DateTime.Now;
                }
            }
        }

        /// <summary>
        /// 解析接收到的数据包
        /// </summary>
        /// <param name="data">接收到的数据</param>
        private void ParseReceivedData(byte[] data)
        {
            lock (_lock)
            {
                if (data.Length < 5) return;

                byte address = data[0];
                byte opCode = data[1];
                byte dataLength = data[2];

                if (data.Length < 3 + dataLength + 2) return;

                byte[] registerData = new byte[dataLength];
                Array.Copy(data, 3, registerData, 0, dataLength);

                ParseRegisterValues(registerData);
            }
        }

        /// <summary>
        /// 解析寄存器值并更新缓存
        /// </summary>
        /// <param name="data">寄存器数据</param>
        private void ParseRegisterValues(byte[] data)
        {
            lock (_lock)
            {
                for (int i = 0; i < data.Length; i += 2)
                {
                    if (i + 1 >= data.Length) break;

                    int registerAddress = i / 2;
                    Int16 registerValue = (Int16)((data[i] << 8) | data[i + 1]);

                    if (!_registerValues.ContainsKey(registerAddress))
                    {
                        _registerValues[registerAddress] = new List<Int16>();
                    }

                    var registerHistory = _registerValues[registerAddress];
                    registerHistory!.Add(registerValue);

                    if (registerHistory.Count > MaxHistorySize)
                    {
                        registerHistory.RemoveAt(0);
                    }
                }
            }
        }

        /// <summary>
        /// 获取指定通道的当前电压原始值
        /// </summary>
        /// <param name="registerAddress">通道地址(0-11)</param>
        /// <returns>当前电压原始值</returns>
        public Int16 GetRegisterValue(int registerAddress)
        {
            lock (_lock)
            {
                if (_registerValues.TryGetValue(registerAddress, out List<short>? values) && values!.Count > 0)
                {
                    return values.Last();
                }
                else
                {
                    MyLog.Debug($"Register {registerAddress} not found. Returning default value 0.");
                    return 0;
                }
            }
        }

        /// <summary>
        /// 获取指定通道的所有历史电压原始值
        /// </summary>
        /// <param name="registerAddress">通道地址(0-11)</param>
        /// <returns>历史电压原始值列表</returns>
        public List<Int16> GetRegisterHistory(int registerAddress)
        {
            lock (_lock)
            {
                if (_registerValues.TryGetValue(registerAddress, out List<short>? values))
                {
                    return values!.ToList();
                }
                else
                {
                    MyLog.Debug($"Register {registerAddress} not found. Returning empty list.");
                    return new List<Int16>();
                }
            }
        }

        /// <summary>
        /// 清空所有通道的历史数据缓存
        /// </summary>
        public void ClearRegisterValues()
        {
            lock (_lock)
            {
                _registerValues.Clear();
                MyLog.Debug("Register values cache cleared.");
            }
        }

        /// <summary>
        /// 断开TCP连接并停止所有任务
        /// </summary>
        public void Disconnect()
        {
            _cancellationTokenSource.Cancel();
            _client?.Close();
            MyLog.Debug("Client disconnected.");
        }
    }
}